package com.weihua.modbus;

import com.intelligt.modbus.jlibmodbus.Modbus;
import com.intelligt.modbus.jlibmodbus.master.ModbusMaster;
import com.intelligt.modbus.jlibmodbus.master.ModbusMasterFactory;
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;
import com.intelligt.modbus.jlibmodbus.utils.DataUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.net.InetAddress;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Data
public class ModbusContext {

    private Integer slave;
    private ModbusMaster master;

    private Map<String, List> funData = new ConcurrentHashMap<>();

    public ModbusContext(int slave, ModbusMaster master){
        this.slave = slave;
        this.master = master;
    }
    public static void main(String[] args) throws Exception {
        TcpParameters tcpParameters = new TcpParameters();
        InetAddress address = InetAddress.getByName("127.0.0.1");
        tcpParameters.setHost(address);
        tcpParameters.setKeepAlive(true);
        tcpParameters.setPort(Modbus.TCP_PORT);
        ModbusMaster m = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
        Modbus.setAutoIncrementTransactionId(true);
        int slaveId = 1;
        int offset = 0;
        int quantity = 10;
        if (!m.isConnected()){
            m.connect();
        }
        int[] rvalues = m.readInputRegisters(slaveId, offset, quantity);
        boolean[] rcs = m.readCoils(slaveId, offset, quantity);
        int[] rhs = m.readHoldingRegisters(slaveId, offset, quantity);
        boolean[] rrs = m.readDiscreteInputs(slaveId, offset, quantity);

        for (int i = 0; i<10; i++){
            log.info("FN-01读取线圈值为：{}==={}", i,rcs[i]);
            log.info("FN-02读取输入状态为:{}==={}",i,rrs[i]);
            log.info("FN-03读取寄存器值为:{}==={}",i, rhs[i]);
            log.info("FN-04读取输入寄存值:{}==={}",i, rvalues[i]);
        }
        log.info(((float)rhs[2]/10)+"");
        byte[] ins = DataUtils.toByteArray(16712);
        //转成浮点行数据[65, 72, 0, 0, 64, 1, -58, -89, -17, -99, -78, 45, 0, 0, 0, 0, 0, 0, 0, 0]
        byte[] bs = {(byte) 0,(byte) 0,(byte) 65,(byte) 72};//将符号位进行转换
        log.info(DataUtils.toFloat(bs)+"");
        //转成二进制数据
        byte[] ebs = { (byte) 1,(byte) 64};//低位和高位转换
        boolean[] booleans = DataUtils.toBitsArray(ebs, 16);
        log.info(booleans.length+"");
    }

    /**
     * 读取F04功能数据信息
     * @param offset
     * @param quantity
     * @return
     */
    public int[] readInputRegisters(int offset, int quantity){
        try {
            return master.readInputRegisters(slave, offset, quantity);
        } catch (Exception e) {
            log.error("读取输入寄存器失败：{}", e.getMessage());
        }
        return new int[0];
    }

    /**
     * 读取F03功能数据信息
     * @param offset
     * @param quantity
     * @return
     */
    public int[] readHoldingRegisters(int offset, int quantity){
        try {
            return master.readHoldingRegisters(slave, offset, quantity);
        } catch (Exception e) {
            log.error("读取保持寄存器失败：{}", e.getMessage());
        }
        return new int[0];
    }

    /**
     * 读取F01功能数据信息
     * @param offset
     * @param quantity
     * @return
     */
    public boolean[] readCoils(int offset, int quantity){
        try {
            return master.readCoils(slave, offset, quantity);
        } catch (Exception e) {
            log.error("读取线圈失败：{}", e.getMessage());
        }
        return new boolean[0];
    }

    /**
     * 读取F02功能数据信息
     * @param offset
     * @param quantity
     * @return
     */
    public boolean[] readDiscreteInputs(int offset, int quantity){
        try {
            return master.readDiscreteInputs(slave, offset, quantity);
        } catch (Exception e) {
            log.error("读取输入量信息失败：{}", e.getMessage());
        }
        return new boolean[0];
    }

    public void clearFunData(){
        funData.clear();
    }
}
